From 87a9ee252146f0ff026e085880e7322b90bec3a4 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 1 Mar 2007 11:38:55 +0000 Subject: [PATCH] xen: Cleanups and bug fixes after the rcu_lock_domain patch. Signed-off-by: Keir Fraser --- xen/arch/ia64/vmx/vmx_hypercall.c | 3 +-- xen/arch/ia64/xen/mm.c | 15 +++++++++------ xen/arch/powerpc/mm.c | 12 ++++++++---- xen/arch/x86/hvm/hvm.c | 14 ++++---------- xen/arch/x86/mm.c | 22 ++++++++++------------ xen/common/domain.c | 5 ++--- xen/common/domctl.c | 6 ++---- xen/common/event_channel.c | 2 +- xen/common/grant_table.c | 14 ++------------ xen/common/schedule.c | 4 ++-- xen/common/sysctl.c | 7 ------- xen/include/xen/sched.h | 14 ++++++++++++++ 12 files changed, 55 insertions(+), 63 deletions(-) diff --git a/xen/arch/ia64/vmx/vmx_hypercall.c b/xen/arch/ia64/vmx/vmx_hypercall.c index 24bde7d094..46a9bdb87f 100644 --- a/xen/arch/ia64/vmx/vmx_hypercall.c +++ b/xen/arch/ia64/vmx/vmx_hypercall.c @@ -122,8 +122,7 @@ do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) return -EINVAL; if (a.domid == DOMID_SELF) { - get_knownalive_domain(current->domain); - d = current->domain; + d = get_current_domain(); } else if (IS_PRIV(current->domain)) { d = get_domain_by_id(a.domid); diff --git a/xen/arch/ia64/xen/mm.c b/xen/arch/ia64/xen/mm.c index b1efa6293f..543ffa1e4d 100644 --- a/xen/arch/ia64/xen/mm.c +++ b/xen/arch/ia64/xen/mm.c @@ -435,11 +435,15 @@ share_xen_page_with_guest(struct page_info *page, page_set_owner(page, d); wmb(); /* install valid domain ptr before updating refcnt. */ ASSERT(page->count_info == 0); - page->count_info |= PGC_allocated | 1; - if ( unlikely(d->xenheap_pages++ == 0) ) - get_knownalive_domain(d); - list_add_tail(&page->list, &d->xenpage_list); + /* Only add to the allocation list if the domain isn't dying. */ + if ( !test_bit(_DOMF_dying, &d->domain_flags) ) + { + page->count_info |= PGC_allocated | 1; + if ( unlikely(d->xenheap_pages++ == 0) ) + get_knownalive_domain(d); + list_add_tail(&page->list, &d->xenpage_list); + } // grant_table_destroy() releases these pages. // but it doesn't clear their m2p entry. So there might remain stale @@ -2057,8 +2061,7 @@ arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) return -EFAULT; if (xatp.domid == DOMID_SELF) { - d = current->domain; - get_knownalive_domain(d); + d = get_current_domain(); } else if (!IS_PRIV(current->domain)) return -EPERM; diff --git a/xen/arch/powerpc/mm.c b/xen/arch/powerpc/mm.c index ab83d09b55..5f257dcc85 100644 --- a/xen/arch/powerpc/mm.c +++ b/xen/arch/powerpc/mm.c @@ -80,11 +80,15 @@ void share_xen_page_with_guest( page_set_owner(page, d); wmb(); /* install valid domain ptr before updating refcnt. */ ASSERT(page->count_info == 0); - page->count_info |= PGC_allocated | 1; - if ( unlikely(d->xenheap_pages++ == 0) ) - get_knownalive_domain(d); - list_add_tail(&page->list, &d->xenpage_list); + /* Only add to the allocation list if the domain isn't dying. */ + if ( !test_bit(_DOMF_dying, &d->domain_flags) ) + { + page->count_info |= PGC_allocated | 1; + if ( unlikely(d->xenheap_pages++ == 0) ) + get_knownalive_domain(d); + list_add_tail(&page->list, &d->xenpage_list); + } spin_unlock(&d->page_alloc_lock); } diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 073ad836d2..bda506b182 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -836,20 +836,14 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) return -EINVAL; if ( a.domid == DOMID_SELF ) - { - get_knownalive_domain(current->domain); - d = current->domain; - } + d = rcu_lock_current_domain(); else if ( IS_PRIV(current->domain) ) - { d = rcu_lock_domain_by_id(a.domid); - if ( d == NULL ) - return -ESRCH; - } else - { return -EPERM; - } + + if ( d == NULL ) + return -ESRCH; rc = -EINVAL; if ( !is_hvm_domain(d) ) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 358ae84081..10f5a86b4d 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -263,11 +263,15 @@ void share_xen_page_with_guest( page_set_owner(page, d); wmb(); /* install valid domain ptr before updating refcnt. */ ASSERT(page->count_info == 0); - page->count_info |= PGC_allocated | 1; - if ( unlikely(d->xenheap_pages++ == 0) ) - get_knownalive_domain(d); - list_add_tail(&page->list, &d->xenpage_list); + /* Only add to the allocation list if the domain isn't dying. */ + if ( !test_bit(_DOMF_dying, &d->domain_flags) ) + { + page->count_info |= PGC_allocated | 1; + if ( unlikely(d->xenheap_pages++ == 0) ) + get_knownalive_domain(d); + list_add_tail(&page->list, &d->xenpage_list); + } spin_unlock(&d->page_alloc_lock); } @@ -2960,10 +2964,7 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) return -EFAULT; if ( xatp.domid == DOMID_SELF ) - { - d = current->domain; - get_knownalive_domain(d); - } + d = rcu_lock_current_domain(); else if ( !IS_PRIV(current->domain) ) return -EPERM; else if ( (d = rcu_lock_domain_by_id(xatp.domid)) == NULL ) @@ -3039,10 +3040,7 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) return -EINVAL; if ( fmap.domid == DOMID_SELF ) - { - d = current->domain; - get_knownalive_domain(d); - } + d = rcu_lock_current_domain(); else if ( !IS_PRIV(current->domain) ) return -EPERM; else if ( (d = rcu_lock_domain_by_id(fmap.domid)) == NULL ) diff --git a/xen/common/domain.c b/xen/common/domain.c index 551b9f8e23..c1a1dc2b4e 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -345,8 +345,7 @@ void domain_pause_for_debugger(void) send_guest_global_virq(dom0, VIRQ_DEBUGGER); } -/* Complete domain destroy after RCU readers are not holding - old references */ +/* Complete domain destroy after RCU readers are not holding old references. */ static void complete_domain_destroy(struct rcu_head *head) { struct domain *d = container_of(head, struct domain, rcu); @@ -390,7 +389,7 @@ void domain_destroy(struct domain *d) rcu_assign_pointer(*pd, d->next_in_hashbucket); spin_unlock(&domlist_update_lock); - /* schedule RCU asynchronous completion of domain destroy */ + /* Schedule RCU asynchronous completion of domain destroy. */ call_rcu(&d->rcu, complete_domain_destroy); } diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 50479532bc..fd85b8cbd8 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -484,22 +484,20 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) break; } - if ( (d == NULL) || !get_domain(d) ) + if ( d == NULL ) { rcu_read_unlock(&domlist_read_lock); ret = -ESRCH; break; } - rcu_read_unlock(&domlist_read_lock); - getdomaininfo(d, &op->u.getdomaininfo); op->domain = op->u.getdomaininfo.domain; if ( copy_to_guest(u_domctl, op, 1) ) ret = -EFAULT; - put_domain(d); + rcu_read_unlock(&domlist_read_lock); } break; diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index 9a786ad4a0..2b361f501e 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -434,7 +434,7 @@ static long __evtchn_close(struct domain *d1, int port1) spin_unlock(&d2->evtchn_lock); put_domain(d2); } - + spin_unlock(&d1->evtchn_lock); return rc; diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index b0818311b0..68d1fa2d8c 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -1086,26 +1086,16 @@ __gnttab_copy( "only allow copy-by-mfn for DOMID_SELF.\n"); if ( op->source.domid == DOMID_SELF ) - { - sd = current->domain; - get_knownalive_domain(sd); - } + sd = rcu_lock_current_domain(); else if ( (sd = rcu_lock_domain_by_id(op->source.domid)) == NULL ) - { PIN_FAIL(error_out, GNTST_bad_domain, "couldn't find %d\n", op->source.domid); - } if ( op->dest.domid == DOMID_SELF ) - { - dd = current->domain; - get_knownalive_domain(dd); - } + dd = rcu_lock_current_domain(); else if ( (dd = rcu_lock_domain_by_id(op->dest.domid)) == NULL ) - { PIN_FAIL(error_out, GNTST_bad_domain, "couldn't find %d\n", op->dest.domid); - } if ( src_is_gref ) { diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 8f1f755d27..8ba192d0ac 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -430,12 +430,12 @@ ret_t do_sched_op(int cmd, XEN_GUEST_HANDLE(void) arg) break; ret = -ESRCH; - d = get_domain_by_id(sched_remote_shutdown.domain_id); + d = rcu_lock_domain_by_id(sched_remote_shutdown.domain_id); if ( d == NULL ) break; domain_shutdown(d, (u8)sched_remote_shutdown.reason); - put_domain(d); + rcu_unlock_domain(d); ret = 0; break; diff --git a/xen/common/sysctl.c b/xen/common/sysctl.c index 399523ecfd..789e643ff2 100644 --- a/xen/common/sysctl.c +++ b/xen/common/sysctl.c @@ -86,16 +86,9 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl) continue; if ( num_domains == op->u.getdomaininfolist.max_domains ) break; - if ( (d == NULL) || !get_domain(d) ) - { - ret = -ESRCH; - break; - } getdomaininfo(d, &info); - put_domain(d); - if ( copy_to_guest_offset(op->u.getdomaininfolist.buffer, num_domains, &info, 1) ) { diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 6fb03a807f..cbfb67a9e7 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -258,6 +258,14 @@ static inline void get_knownalive_domain(struct domain *d) ASSERT(!(atomic_read(&d->refcnt) & DOMAIN_DESTROYED)); } +/* Obtain a reference to the currently-running domain. */ +static inline struct domain *get_current_domain(void) +{ + struct domain *d = current->domain; + get_knownalive_domain(d); + return d; +} + struct domain *domain_create(domid_t domid, unsigned int domcr_flags); /* DOMCRF_hvm: Create an HVM domain, as opposed to a PV domain. */ #define _DOMCRF_hvm 0 @@ -284,6 +292,12 @@ static inline void rcu_unlock_domain(struct domain *d) rcu_read_unlock(&domlist_read_lock); } +static inline struct domain *rcu_lock_current_domain(void) +{ + rcu_read_lock(&domlist_read_lock); + return current->domain; +} + struct domain *get_domain_by_id(domid_t dom); void domain_destroy(struct domain *d); void domain_kill(struct domain *d); -- 2.30.2